package com.mk.interceptor;

import act.app.ActionContext;
import act.controller.Controller;
import act.event.ActEvent;
import act.event.EventBus;
import act.event.On;
import act.util.Global;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.mk.domain.CpUser;
import com.mk.domain.CpWebErr;
import com.mk.enums.ErrorCode;
import com.mk.exception.UserException;
import com.mk.util.MapUtil;
import com.mk.util.Redis;
import com.mk.util.S2;
import org.beetl.sql.core.JavaType;
import org.osgl.exception.UnexpectedException;
import org.osgl.mvc.annotation.Before;
import org.osgl.mvc.annotation.Catch;
import org.osgl.mvc.result.Result;
import org.osgl.util.C;
import org.osgl.util.S;
import org.rythmengine.exception.CompileException;

import javax.inject.Singleton;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Types;
import java.util.Map;

/**
 * 通用
 * 异常、beetl类型修正
 */
@SuppressWarnings("unused")
@Singleton
public class ICommon extends Controller.Base {
    @Catch @Global
    public Result internalHandle(Exception e, ActionContext context, EventBus eventBus) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        eventBus.trigger("web-error", new ActEvent<>(C.Map(
            "e", sw.toString(),
            "message", e.getMessage(),
            "params", JSON.toJSONString(context.allParams()),
            "ip", context.req().ip(),
            "url", context.req().url(),
            "devid", context.req().header("devid")
        )));
        if (e instanceof UnexpectedException) {
            return handel(ErrorCode.E200001.status(), e.getMessage(), context);
        } else if (e instanceof UserException) {
            UserException ex = (UserException) e;
            return handel(ex.getStatus(), e.getMessage(), context);
        } else if (e instanceof NullPointerException) {
            return handel(ErrorCode.E200000.status(), e.getMessage(), context);
        } else if (e instanceof CompileException) {
            return null;
        } else {
            return handel(ErrorCode.E100001.status(), e.getMessage(), context);
        }
    }

    @Before @Global
    public void fix() {
        JavaType.jdbcJavaTypes.put(Types.VARBINARY, String.class);
    }

    private Result handel(String status, String message, ActionContext context) {
        return renderJson(C.Map("status", status, "message", message));
    }

    @On(value = "web-error", async = true)
    public void addEditRecord(ActEvent<Map<String, Object>> event, CpWebErr.Mapper mapper) {
        Map<String, Object> eventSource = event.source();
        String e = MapUtil.get(eventSource, "e");
        String message = MapUtil.get(eventSource, "message");
        String params = MapUtil.get(eventSource, "params");
        String ip = MapUtil.get(eventSource, "ip");
        String url = MapUtil.get(eventSource, "url");
        String devid = MapUtil.get(eventSource, "devid");

        CpWebErr webErr = new CpWebErr();
        webErr.setOpid(S2.UUID());
//        if (S.isNotBlank(devid)) {
////            CpUser user = CacheUtil.cached(null, devid, CpUser.class, CacheUtil.REDIS);
//            CpUser user = Redis.userDb.getBucket(devid, CpUser.class).get();
//            if (user != null) {
//                webErr.setOpusername(S2.electOneNotBlank(user.getRealname(), user.getNickname()));
//                webErr.setOpuserid(user.getUserid());
//                webErr.setSpid(user.getSpid());
//            }
//        }
        webErr.setOppath(url);
        webErr.setOpdate(DateUtil.now());
        webErr.setOpip(ip);
        webErr.setOperror(e);
        webErr.setOpparam(params);
        webErr.setOpmessage(message);
        mapper.insertTemplate(webErr);
    }

}
